{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "initial_id",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    ""
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 举例1：大模型分析工具的调用",
   "id": "e0898868d5a13502"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-30T02:11:55.799001Z",
     "start_time": "2025-09-30T02:11:52.563903Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\n",
    "# 1、获取大模型\n",
    "#导入相关依赖\n",
    "from langchain_community.tools import MoveFileTool\n",
    "from langchain_core.messages import HumanMessage\n",
    "from langchain_core.tools import StructuredTool\n",
    "from langchain_core.utils.function_calling import convert_to_openai_function\n",
    "import os\n",
    "import dotenv\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "dotenv.load_dotenv()\n",
    "\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv(\"OPENAI_API_KEY1\")\n",
    "os.environ['OPENAI_BASE_URL'] = os.getenv(\"OPENAI_BASE_URL\")\n",
    "\n",
    "# 定义LLM模型\n",
    "chat_model = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n",
    "\n",
    "# 2、获取工具的列表\n",
    "tools = [MoveFileTool()]\n",
    "\n",
    "# 3、因为大模型invoke调用时，需要传入函数的列表，所以需要将工具转换为函数:convert_to_openai_function()\n",
    "functions = [convert_to_openai_function(t) for t in tools]\n",
    "\n",
    "# 4、获取消息列表\n",
    "messages = [HumanMessage(content=\"将文件a移动到/Users/shishizan/Downloads/aaa目录下\") ]\n",
    "\n",
    "\n",
    "# 5、调用大模型（传入消息列表、工具的列表）\n",
    "response = chat_model.invoke(\n",
    "    input=messages,\n",
    "    # tools = tools, #不支持\n",
    "    functions=functions,\n",
    ")\n",
    "print(response)"
   ],
   "id": "3c0a08a4c69130aa",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/miniconda3/envs/pyth310/lib/python3.10/site-packages/requests/__init__.py:86: RequestsDependencyWarning: Unable to find acceptable character detection dependency (chardet or charset_normalizer).\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "content='' additional_kwargs={'function_call': {'arguments': '{\"source_path\":\"a\",\"destination_path\":\"/Users/shishizan/Downloads/aaa/a\"}', 'name': 'move_file'}, 'refusal': None} response_metadata={'token_usage': {'completion_tokens': 30, 'prompt_tokens': 85, 'total_tokens': 115, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_efad92c60b', 'id': 'chatcmpl-CLK8IPV0See9DpVWyZr7CK5htOF3Z', 'service_tier': None, 'finish_reason': 'function_call', 'logprobs': None} id='run--4dcab3fe-1e52-4d70-804f-89fc5f59a4d4-0' usage_metadata={'input_tokens': 85, 'output_tokens': 30, 'total_tokens': 115, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "作为对比：",
   "id": "440eb3137139bf7a"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-30T02:17:20.166045Z",
     "start_time": "2025-09-30T02:17:18.952606Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\n",
    "# 获取消息列表\n",
    "messages = [HumanMessage(content=\"查询一下明天北京的天气\")]\n",
    "\n",
    "# 调用大模型（传入消息列表、工具的列表）\n",
    "response = chat_model.invoke(\n",
    "    input=messages,\n",
    "    # tools = tools, #不支持\n",
    "    functions=functions,\n",
    ")\n",
    "\n",
    "print(response)"
   ],
   "id": "f5b270dae7a06de2",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "content='抱歉，我无法提供实时的天气信息。建议您查看天气预报网站或使用天气应用程序获取最新的天气信息。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 30, 'prompt_tokens': 76, 'total_tokens': 106, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_efad92c60b', 'id': 'chatcmpl-CLKDXPh6Ug8XRry03BOJBOD01Bk0X', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None} id='run--6fb699a7-7574-4150-89d9-9dfd574d1809-0' usage_metadata={'input_tokens': 76, 'output_tokens': 30, 'total_tokens': 106, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}\n"
     ]
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "通过上面两个测试发现，得到的AIMessage的核心属性如下：\n",
    "\n",
    "1、如果分析出需要调用对应的工具：\n",
    "\n",
    "content：信息为空。因为大模型要调用工具，所以就不会直接返回信息给用户\n",
    "\n",
    "additional_kwargs：包含function_call字段，指明具体函数调用的参数和函数名。比如：\n",
    "\n",
    "additional_kwargs={'function_call': {'arguments': '{\"source_path\":\"a\",\"destination_path\":\"/Users/YourUsername/Desktop/a\"}', 'name': 'move_file'}, 'refusal': None}\n",
    "\n",
    "2、如果分析出不需要调用对应的工具：\n",
    "\n",
    "content：信息不为空。\n",
    "\n",
    "additional_kwargs：不包含function_call字段\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ],
   "id": "532171d27e2bbe63"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 举例2：如何调用具体大模型分析出来的工具\n",
    "\n",
    "说明：\n",
    "\n",
    "1、大模型与Agent的核心区别：是否涉及到工具的调用\n",
    "\n",
    "2、针对于大模型：仅能分析出要调用的工具，但是此工具（或函数）不能真正的执行\n",
    "\n",
    "   针对于Agent:除了分析出要调用的工具之外，还可以执行具体的工具（或函数）"
   ],
   "id": "d93cd0a5ec34186d"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-30T02:30:57.352393Z",
     "start_time": "2025-09-30T02:30:56.081721Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\n",
    "# 1、获取大模型\n",
    "#导入相关依赖\n",
    "from langchain_community.tools import MoveFileTool\n",
    "from langchain_core.messages import HumanMessage\n",
    "from langchain_core.utils.function_calling import convert_to_openai_function\n",
    "import os\n",
    "import dotenv\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "dotenv.load_dotenv()\n",
    "\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv(\"OPENAI_API_KEY1\")\n",
    "os.environ['OPENAI_BASE_URL'] = os.getenv(\"OPENAI_BASE_URL\")\n",
    "\n",
    "# 定义LLM模型\n",
    "chat_model = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n",
    "\n",
    "# 2、获取工具的列表\n",
    "tools = [MoveFileTool()]\n",
    "\n",
    "# 3、因为大模型invoke调用时，需要传入函数的列表，所以需要将工具转换为函数:convert_to_openai_function()\n",
    "functions = [convert_to_openai_function(t) for t in tools]\n",
    "\n",
    "# 4、获取消息列表\n",
    "messages = [HumanMessage(content=\"将当前目录下的文件a.txt移动到/Users/shishizan/Downloads/aaa\")]\n",
    "\n",
    "# 5、调用大模型（传入消息列表、工具的列表）\n",
    "response = chat_model.invoke(\n",
    "    input=messages,\n",
    "    # tools = tools, #不支持\n",
    "    functions=functions,\n",
    ")\n",
    "\n",
    "# print(response)"
   ],
   "id": "3ae942ec35ddd5c0",
   "outputs": [],
   "execution_count": 3
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "步骤1：分析下要调用哪个工具或函数",
   "id": "e861148cfd354327"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-30T02:31:02.620591Z",
     "start_time": "2025-09-30T02:31:02.612212Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\n",
    "import json\n",
    "\n",
    "if \"function_call\" in response.additional_kwargs:\n",
    "    tool_name = response.additional_kwargs[\"function_call\"][\"name\"]\n",
    "    tool_args = json.loads(response.additional_kwargs[\"function_call\"][\"arguments\"])\n",
    "    print(f\"调用工具：{tool_name} \\n 参数：{tool_args}\")\n",
    "\n",
    "else:\n",
    "    print(f\"模型回复：{response.content}\")"
   ],
   "id": "7f5c011b4ed7c91d",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "调用工具：move_file \n",
      " 参数：{'source_path': 'a.txt', 'destination_path': '/Users/shishizan/Downloads/aaa/a.txt'}\n"
     ]
    }
   ],
   "execution_count": 4
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "步骤2：调用对应的工具",
   "id": "3425ad124cdc809a"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-30T02:31:08.455415Z",
     "start_time": "2025-09-30T02:31:08.445963Z"
    }
   },
   "cell_type": "code",
   "source": [
    "if \"move_file\" in response.additional_kwargs[\"function_call\"][\"name\"]:\n",
    "    tool = MoveFileTool()\n",
    "    result = tool.run(tool_args)  #调用工具\n",
    "    print(\"工具执行的结果\", result)"
   ],
   "id": "a89590ae16874879",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "工具执行的结果 File moved successfully from a.txt to /Users/shishizan/Downloads/aaa/a.txt.\n"
     ]
    }
   ],
   "execution_count": 5
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
